﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ICSharpCode.WinFormsUI.Controls
{
    public class NDataGridView : System.Windows.Forms.DataGridView
    {
        private string editing_model = "undefined";
        private DataGridViewPrinter MyDataGridViewPrinter;
        private System.Drawing.Printing.PrintDocument MyPrintDocument;

        public NDataGridView()
        {            
            InitializeControl();
        }

        #region 属性

        private bool _ShowRowNumber;
        /// <summary>
        /// 是否显示行号
        /// </summary>
        public bool ShowRowNumber
        {
            get { return _ShowRowNumber; }
            set { _ShowRowNumber = value; }
        }


        private object _DataSource;
        public new object DataSource
        {
            get
            {
                return _DataSource;
            }
            set
            {
                _DataSource = value;
                BindDataSource();
            }
        }

        public ShowToastValue ShowToastValue;

        #endregion

        protected void InitializeControl()
        {
            this.MyPrintDocument = new System.Drawing.Printing.PrintDocument();
            this.MyPrintDocument.PrintPage += OnPrintDocument_PrintPage;             
            this.ShowRowNumber = false;
            this.DoubleBuffered = true;            
        }

        protected override void OnDataError(bool displayErrorDialogIfNoHandler, System.Windows.Forms.DataGridViewDataErrorEventArgs e)
        {
            //base.OnDataError(displayErrorDialogIfNoHandler, e);
            if (e.RowIndex > -1 && e.ColumnIndex > -1)
            {
                DataGridViewCell cell = this.Rows[e.RowIndex].Cells[e.ColumnIndex];
                DoDataError(cell, e.Context);
                cell.ErrorText = e.Exception.Message;
            }
        }

        protected override void OnCellFormatting(DataGridViewCellFormattingEventArgs e)
        {
            base.OnCellFormatting(e);
            if (Type.Equals(e.DesiredType, typeof(System.Drawing.Image)))
            {
                if (e.RowIndex > -1 && e.ColumnIndex > -1)
                {
                    //this.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = e.Value;
                    e.Value = DoDataImage(e.Value, e.RowIndex, e.ColumnIndex);
                }
            }

        }

        protected override void OnCellClick(DataGridViewCellEventArgs e)
        {
            base.OnCellClick(e);
            if (this.ShowToastValue != null)
            {
                if (e.RowIndex > -1 && e.ColumnIndex > -1)
                {
                    DataGridViewCell cell = this.Rows[e.RowIndex].Cells[e.ColumnIndex];
                    if (cell.FormattedValueType.Equals(typeof(System.Drawing.Image)) && cell.ValueType.Equals(typeof(Byte[])))
                    {
                        var Value = cell.Value;
                        try
                        {
                            Byte[] array = (Byte[])Value;
                            using (System.IO.Stream stream = new System.IO.MemoryStream(array))
                            {
                                //stream.Read(array, 0, array.Length);
                                Image image = (Bitmap)Image.FromStream(stream, true);
                            }
                        }
                        catch
                        {
                            this.ShowToastValue(this, new ToastEventArgs() { Value = cell.Value });
                        }                        
                    }
                }
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (this.BorderStyle == BorderStyle.None)
            {
                Graphics g = e.Graphics;
                g.DrawRectangle(new Pen(SystemColors.ControlDark), this.ClientRectangle);
            }
        }

        protected override void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e)
        {
            base.OnRowPostPaint(e);           
            if (this._ShowRowNumber)
            {
                if (e.RowIndex > -1)
                {
                    System.Drawing.Rectangle rectangle =
                    new System.Drawing.Rectangle(e.RowBounds.Location.X,
                                     e.RowBounds.Location.Y,
                                     this.RowHeadersWidth - 4,
                                     e.RowBounds.Height);

                    TextRenderer.DrawText(e.Graphics, (e.RowIndex + 1).ToString(),
                        this.RowHeadersDefaultCellStyle.Font,
                        rectangle,
                        this.RowHeadersDefaultCellStyle.ForeColor,
                        TextFormatFlags.VerticalCenter | TextFormatFlags.Right);
                }                 
            }
        }

        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
        {
            base.OnCellPainting(e);
            if (e.RowIndex == -1)
            {
                OnRedrawCell(this, e);
            }
            if (e.RowIndex > -1 && e.ColumnIndex == -1)
            {
                OnRedrawCell(this, e);
            }
        }

        protected override void OnCellBeginEdit(DataGridViewCellCancelEventArgs e)
        {            
            base.OnCellBeginEdit(e);
            this.editing_model = "start_edit";
        }

        protected override void OnCellEndEdit(DataGridViewCellEventArgs e)
        {            
            base.OnCellEndEdit(e);
            this.editing_model = "end_edit";
        }

        protected virtual Image DoDataImage(object Value, int RowIndex, int ColumnIndex)
        {
            int width = 100; int height = 22;
            Bitmap image = new Bitmap(width, height);

            try
            {
                Byte[] array = (Byte[])Value;
                using (System.IO.Stream stream = new System.IO.MemoryStream(array))
                {
                    //stream.Read(array, 0, array.Length);
                    image = (Bitmap)Image.FromStream(stream, true);
                }
            }
            catch (Exception ex)
            {
                //if (this.Columns[ColumnIndex].Width != width &&
                //     this.Columns[ColumnIndex].Resizable != DataGridViewTriState.False)
                //{
                //    this.Columns[ColumnIndex].Width = width;
                //    this.Columns[ColumnIndex].Resizable = DataGridViewTriState.False;
                //}

                if (this.Columns[ColumnIndex].Resizable != DataGridViewTriState.False)
                {
                    this.Columns[ColumnIndex].Resizable = DataGridViewTriState.False;
                }

                var cell = this.Rows[RowIndex].Cells[ColumnIndex];
                image = new Bitmap(cell.OwningColumn.Width, cell.OwningRow.Height);

                using (Graphics graphic = Graphics.FromImage(image))
                {
                    using (Brush _bru = new SolidBrush(cell.Style.BackColor))
                    {
                        graphic.FillRectangle(_bru, new Rectangle(0, 0, image.Width, image.Height));
                    }

                    if (Value != null && Value != DBNull.Value)
                    {
                        StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Center };
                        string strValue = string.Empty;

                        //System.Text.Encoding.Default.GetString((Byte[])Value);

                        //StringBuilder sb = new StringBuilder();
                        //Byte[] array = (Byte[])Value;
                        //for (int i = 0; i < array.Length; i++)
                        //{
                        //    sb.Append(array[i].ToString("X2"));
                        //}
                        //strValue = "Ox" + sb.ToString();

                        strValue = "Byte[] 字节流";

                        if (!string.IsNullOrEmpty(strValue) && strValue.Length > 16)
                            strValue = string.Concat(strValue.Substring(0, 16), "...");

                        graphic.DrawString(strValue, this.Font, Brushes.Black, new Rectangle(0, 0, image.Width, image.Height), sf);
                    }

                }
            }

            return image;
        }

        protected virtual void DoDataError(DataGridViewCell cell, DataGridViewDataErrorContexts context)
        {
            //if (cell.FormattedValue != null) //&& cell.FormattedValue.GetType().Equals(typeof(System.Drawing.Bitmap))
            //{
            //    Bitmap image = new Bitmap(cell.OwningColumn.Width, cell.OwningRow.Height);
            //    Graphics graphic = Graphics.FromImage(image);
            //    using (Brush _bru = new SolidBrush(cell.Style.BackColor))
            //    {
            //        graphic.FillRectangle(_bru, new Rectangle(0, 0, image.Width, image.Height));
            //    }

            //    var Value = cell.Value;
            //    if (Value != null && Value != DBNull.Value)
            //    {
            //        StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Center };
            //        string strValue = System.Text.Encoding.Default.GetString((Byte[])Value);
            //        graphic.DrawString(strValue, this.Font, Brushes.Black, new Rectangle(0, 0, image.Width, image.Height), sf);
            //    }

            //    graphic.Dispose();

            //    cell.Value = image;
            //}            
        }
        
        private void OnPrintDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            bool more = MyDataGridViewPrinter.DrawDataGridView(e.Graphics);
            if (more == true)
                e.HasMorePages = true;
        }

        private void OnRedrawCell(object sender,DataGridViewCellPaintingEventArgs e)
        {
            using (Brush brush = new SolidBrush(SystemColors.Control))
            {
                e.Graphics.FillRectangle(brush, e.CellBounds);
                Rectangle border = e.CellBounds;
                border.Offset(new Point(-1, -1));
                e.Graphics.DrawRectangle(Pens.Gray, border);
            }
            e.PaintContent(e.CellBounds);
            e.Handled = true;
        }

        protected virtual bool SetupThePrinting()
        {
            PrintDialog MyPrintDialog = new PrintDialog();
            MyPrintDialog.AllowCurrentPage = false;
            MyPrintDialog.AllowPrintToFile = false;
            MyPrintDialog.AllowSelection = false;
            MyPrintDialog.AllowSomePages = false;
            MyPrintDialog.PrintToFile = false;
            MyPrintDialog.ShowHelp = false;
            MyPrintDialog.ShowNetwork = false;

            if (MyPrintDialog.ShowDialog() != DialogResult.OK)
                return false;

            MyPrintDocument.DocumentName = "Customers Report";
            MyPrintDocument.PrinterSettings = MyPrintDialog.PrinterSettings;
            MyPrintDocument.DefaultPageSettings = MyPrintDialog.PrinterSettings.DefaultPageSettings;
            MyPrintDocument.DefaultPageSettings.Margins = new Margins(40, 40, 40, 40);

            MyDataGridViewPrinter = new DataGridViewPrinter(this, MyPrintDocument, true, true, "数据报表", new Font("Tahoma", 18, FontStyle.Bold, GraphicsUnit.Point), Color.Black, true);

            return true;
        }
                
        protected virtual void BindDataSource()
        {
            //base.DataSource = null;
            //var source = new DataTable();
            //if (this._DataSource is DataTable)
            //{
            //    source = (DataTable)this._DataSource;
            //}
            //else if (this._DataSource is DataView)
            //{
            //    source = ((DataView)this._DataSource).Table;
            //}
            //else if (this._DataSource is DataSet)
            //{
            //    if (string.IsNullOrEmpty(this.DataMember))
            //    {
            //        source = ((DataSet)this._DataSource).Tables[0];
            //    }
            //}

            //bool reset = false;
            //if (source != null)
            //{
            //    foreach (DataColumn dc in source.Columns)
            //    {
            //        if (string.Equals(dc.DataType.Name, "Byte[]"))
            //        {
            //            reset = true;
            //            break;
            //        }
            //    }
            //}
            //if (reset)
            //{
            //    DataTable _source = new DataTable();
            //    foreach (DataColumn dc in source.Columns)
            //    {
            //        DataColumn _dc = new DataColumn();
            //        if (string.Equals(dc.DataType.Name, "Byte[]"))
            //        {
            //            _dc.DataType = typeof(String);
            //        }
            //        else
            //        {
            //            _dc.DataType = dc.DataType;
            //        }
            //        _dc.ColumnName = dc.ColumnName;
            //        _dc.Caption = dc.Caption;
            //        _source.Columns.Add(_dc);
            //    }

            //    foreach (DataRow dr in source.Rows)
            //    {
            //        DataRow row = _source.NewRow();
            //        foreach (DataColumn dc in source.Columns)
            //        {
            //            if (string.Equals(dc.DataType.Name, "Byte[]"))
            //            {
            //                var Value = dr[dc.ColumnName];
            //                if (Value != null && DBNull.Value != Value)
            //                    row[dc.ColumnName] = System.Text.Encoding.Default.GetString((Byte[])Value);
            //            }
            //            else
            //            {
            //                row[dc.ColumnName] = dr[dc.ColumnName];
            //            }                      
            //        }
            //        _source.Rows.Add(row);
            //    }

            //    _DataSource = _source;
            //    base.DataSource = _source;
            //    this.ReadOnly = true;
            //}
            //else
            //{
            //    base.DataSource = _DataSource;
            //    this.ReadOnly = false;
            //}

            base.DataSource = _DataSource;

        }

        public void PrintPreview()
        {
            if (SetupThePrinting())
            {
                PrintPreviewDialog MyPrintPreviewDialog = new PrintPreviewDialog();                
                MyPrintPreviewDialog.Document = MyPrintDocument;
                MyPrintPreviewDialog.ShowDialog();
            }
        }

        public void Print()
        {
            if (SetupThePrinting())
                MyPrintDocument.Print();
        }

    }

    public class ToastEventArgs : System.EventArgs
    {
        public object Value { get; set; }
    }

    public delegate void ShowToastValue(object sender,ToastEventArgs e);
}
